package cn.dakaqi.services.impl;

import cn.dakaqi.dao.PassportApplyOrderDao;
import cn.dakaqi.entities.PassportApplyOrder;
import cn.dakaqi.entities.PassportApplyOrderPatch;
import cn.dakaqi.services.PassportApplyOrderPatchService;
import cn.dakaqi.services.PassportApplyOrderService;
import cn.dakaqi.utils.exception.ServiceRuntimeException;
import com.google.common.collect.Maps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springside.modules.persistence.DynamicSpecifications;
import org.springside.modules.persistence.SearchFilter;

import java.util.List;
import java.util.Map;

/**
 * Copyright: Copyright (c)2016
 * Company: 志愿者打卡器(www.dakaqi.cn)
 * 类名称: PassportApplyOrderServiceImpl <br>
 * 类描述: <br>
 *
 * @author: ChunYang.Zhang
 * @since: 2016/10/20 9:23
 * @version: 1.0.0
 */
@Transactional
@Component("passportApplyOrderService")
public class PassportApplyOrderServiceImpl implements PassportApplyOrderService
{
    @Autowired
    PassportApplyOrderDao passportApplyOrderDao;
    @Autowired
    PassportApplyOrderPatchService passportApplyOrderPatchService;

    @Transactional
    @Override
    public void saveAndUpdate(PassportApplyOrder newOrder, PassportApplyOrder oldOrder) throws ServiceRuntimeException
    {
        this.passportApplyOrderDao.save(newOrder);
        this.passportApplyOrderDao.save(oldOrder);
    }

    @Override
    public PassportApplyOrder save(PassportApplyOrder passportApplyOrder) throws ServiceRuntimeException
    {
        passportApplyOrderDao.save(passportApplyOrder);
        return passportApplyOrder;
    }

    @Override
    public PassportApplyOrder update(PassportApplyOrder passportApplyOrder) throws ServiceRuntimeException
    {
        this.passportApplyOrderDao.save(passportApplyOrder);
        return passportApplyOrder;
    }

    @Override
    public Page<PassportApplyOrder> findByBaseAddressId(Long baseAddressId,int status,int pageNumber) throws ServiceRuntimeException
    {
        Map<String, SearchFilter> filters = Maps.newHashMap();
        Sort sort =new Sort(Sort.Direction.ASC,"createTime");
        PageRequest pageRequest = new PageRequest(pageNumber - 1, 20, sort);
        filters.put("bassAddressId", new SearchFilter("bassAddressId", SearchFilter.Operator.EQ, baseAddressId));
        filters.put("orderStatus", new SearchFilter("orderStatus", SearchFilter.Operator.EQ, PassportApplyOrder.ORDER_STAUTS_NORMAL));
        if(status<PassportApplyOrder.STAUTS_SEND_WAITE)
            filters.put("status", new SearchFilter("status", SearchFilter.Operator.LT, PassportApplyOrder.STAUTS_SEND_WAITE));
        else
            filters.put("status", new SearchFilter("status", SearchFilter.Operator.EQ, status));

        Specification<PassportApplyOrder> spec = DynamicSpecifications.bySearchFilter(filters.values(), PassportApplyOrder.class);
        return this.passportApplyOrderDao.findAll(spec,pageRequest);
    }

    @Override
    public Page<PassportApplyOrder> findByStatusLogOut(Long baseAddressId, int pageNumber) throws ServiceRuntimeException
    {
        Map<String, SearchFilter> filters = Maps.newHashMap();
        Sort sort = new Sort(Sort.Direction.ASC, "appointmenDate","appointmentTime");
        PageRequest pageRequest = new PageRequest(pageNumber - 1, 200, sort);
        filters.put("bassAddressId", new SearchFilter("bassAddressId", SearchFilter.Operator.EQ, baseAddressId));
        filters.put("status", new SearchFilter("status", SearchFilter.Operator.EQ, PassportApplyOrder.STAUTS_WAITE_LOGOUT));
        Specification<PassportApplyOrder> spec = DynamicSpecifications.bySearchFilter(filters.values(), PassportApplyOrder.class);
        return this.passportApplyOrderDao.findAll(spec,pageRequest);
    }

    @Override
    public PassportApplyOrder findOne(Long id) throws ServiceRuntimeException
    {
        return this.passportApplyOrderDao.findOne(id);
    }

    @Override
    public PassportApplyOrder findByCardNO(Long baseAddressId,int status,String cardNO) throws ServiceRuntimeException
    {
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("bassAddressId", new SearchFilter("bassAddressId", SearchFilter.Operator.EQ, baseAddressId));
        filters.put("cardNO", new SearchFilter("cardNO", SearchFilter.Operator.EQ, cardNO));
        if(status<PassportApplyOrder.STAUTS_SEND_WAITE)
            filters.put("status", new SearchFilter("status", SearchFilter.Operator.LT, PassportApplyOrder.STAUTS_SEND_WAITE));
        else
            filters.put("status", new SearchFilter("status", SearchFilter.Operator.EQ, status));
        filters.put("orderStatus", new SearchFilter("orderStatus", SearchFilter.Operator.EQ, PassportApplyOrder.ORDER_STAUTS_NORMAL));
        Specification<PassportApplyOrder> spec = DynamicSpecifications.bySearchFilter(filters.values(), PassportApplyOrder.class);
        List<PassportApplyOrder> list = this.passportApplyOrderDao.findAll(spec);
        if(null != list && list.size()>0)
            return list.get(list.size()-1);
        return null;
    }

    @Override
    public PassportApplyOrder findByNum(Long baseAddressId,int status,String num) throws ServiceRuntimeException
    {
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("bassAddressId", new SearchFilter("bassAddressId", SearchFilter.Operator.EQ, baseAddressId));
        filters.put("oldNum", new SearchFilter("oldNum", SearchFilter.Operator.EQ, num));
        if(status<PassportApplyOrder.STAUTS_SEND_WAITE)
            filters.put("status", new SearchFilter("status", SearchFilter.Operator.LT, PassportApplyOrder.STAUTS_SEND_WAITE));
        else
            filters.put("status", new SearchFilter("status", SearchFilter.Operator.EQ, status));
        filters.put("orderStatus", new SearchFilter("orderStatus", SearchFilter.Operator.EQ, PassportApplyOrder.ORDER_STAUTS_NORMAL));
        Specification<PassportApplyOrder> spec = DynamicSpecifications.bySearchFilter(filters.values(), PassportApplyOrder.class);
        List<PassportApplyOrder> list = this.passportApplyOrderDao.findAll(spec);
        if(null != list && list.size()>0)
            return list.get(list.size()-1);
        return null;
    }

    @Override
    public PassportApplyOrder findByRealnameAndNum(String realName, String num) throws ServiceRuntimeException
    {
        Map<String, SearchFilter> filters = Maps.newHashMap();
        Sort sort = new Sort(Sort.Direction.ASC, "appointmenDate","appointmentTime");
        PageRequest pageRequest = new PageRequest(0, 20, sort);
        filters.put("oldNum", new SearchFilter("oldNum", SearchFilter.Operator.EQ, num));
        filters.put("name", new SearchFilter("name", SearchFilter.Operator.EQ, realName));
        Specification<PassportApplyOrder> spec = DynamicSpecifications.bySearchFilter(filters.values(), PassportApplyOrder.class);
        List<PassportApplyOrder> list = this.passportApplyOrderDao.findAll(spec);
        if(null != list && list.size()>0)
            return list.get(list.size()-1);
        return null;
    }

    @Override
    public Page<PassportApplyOrder> findByNum(Long baseAddressId, int status, String num, int pageNumber) throws ServiceRuntimeException
    {
        Map<String, SearchFilter> filters = Maps.newHashMap();
        Sort sort = new Sort(Sort.Direction.ASC, "appointmenDate","appointmentTime");
        PageRequest pageRequest = new PageRequest(pageNumber - 1, 20, sort);
        filters.put("bassAddressId", new SearchFilter("bassAddressId", SearchFilter.Operator.EQ, baseAddressId));
        filters.put("oldNum", new SearchFilter("oldNum", SearchFilter.Operator.EQ, num));
        if(status<PassportApplyOrder.STAUTS_SEND_WAITE)
            filters.put("status", new SearchFilter("status", SearchFilter.Operator.LT, PassportApplyOrder.STAUTS_SEND_WAITE));
        else
            filters.put("status", new SearchFilter("status", SearchFilter.Operator.EQ, status));
        filters.put("orderStatus", new SearchFilter("orderStatus", SearchFilter.Operator.EQ, PassportApplyOrder.ORDER_STAUTS_NORMAL));
        Specification<PassportApplyOrder> spec = DynamicSpecifications.bySearchFilter(filters.values(), PassportApplyOrder.class);
        return this.passportApplyOrderDao.findAll(spec,pageRequest);
    }

    @Override
    public PassportApplyOrder findAllNum(String num) throws ServiceRuntimeException
    {
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("oldNum", new SearchFilter("oldNum", SearchFilter.Operator.EQ, num));
        filters.put("orderStatus", new SearchFilter("orderStatus", SearchFilter.Operator.EQ, PassportApplyOrder.ORDER_STAUTS_NORMAL));
        Specification<PassportApplyOrder> spec = DynamicSpecifications.bySearchFilter(filters.values(), PassportApplyOrder.class);
        List<PassportApplyOrder> list = this.passportApplyOrderDao.findAll(spec);
        if(null != list && list.size()>0)
            return list.get(list.size()-1);
        return null;
    }

    @Override
    public PassportApplyOrder findAllCardNO(String cardNO) throws ServiceRuntimeException
    {
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("cardNO", new SearchFilter("cardNO", SearchFilter.Operator.EQ, cardNO));
        Specification<PassportApplyOrder> spec = DynamicSpecifications.bySearchFilter(filters.values(), PassportApplyOrder.class);
        List<PassportApplyOrder> list = this.passportApplyOrderDao.findAll(spec);
        if(null != list && list.size()>0)
            return list.get(list.size()-1);
        return null;
    }

    @Override
    public PassportApplyOrder findByMobile(Long baseAddressId,int status, String mobile) throws ServiceRuntimeException
    {
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("bassAddressId", new SearchFilter("bassAddressId", SearchFilter.Operator.EQ, baseAddressId));
        if(status<PassportApplyOrder.STAUTS_SEND_WAITE)
            filters.put("status", new SearchFilter("status", SearchFilter.Operator.LT, PassportApplyOrder.STAUTS_SEND_WAITE));
        else
            filters.put("status", new SearchFilter("status", SearchFilter.Operator.EQ, status));
        filters.put("mobile", new SearchFilter("mobile", SearchFilter.Operator.EQ, mobile));
        filters.put("orderStatus", new SearchFilter("orderStatus", SearchFilter.Operator.EQ, PassportApplyOrder.ORDER_STAUTS_NORMAL));
        Specification<PassportApplyOrder> spec = DynamicSpecifications.bySearchFilter(filters.values(), PassportApplyOrder.class);
        List<PassportApplyOrder> list = this.passportApplyOrderDao.findAll(spec);
        if(null != list && list.size()>0)
            return list.get(list.size()-1);
        return null;
    }

    @Override
    public Page<PassportApplyOrder> findByCardNO(Long baseAddressId,String cardNO, int status, int pageNumber) throws ServiceRuntimeException
    {
        Map<String, SearchFilter> filters = Maps.newHashMap();
        Sort sort = new Sort(Sort.Direction.DESC, "appointmentTime");
        PageRequest pageRequest = new PageRequest(pageNumber - 1, 20, sort);
        filters.put("bassAddressId", new SearchFilter("bassAddressId", SearchFilter.Operator.EQ, baseAddressId));
        filters.put("orderStatus", new SearchFilter("orderStatus", SearchFilter.Operator.EQ, PassportApplyOrder.ORDER_STAUTS_NORMAL));
        if(status<PassportApplyOrder.STAUTS_SEND_WAITE)
            filters.put("status", new SearchFilter("status", SearchFilter.Operator.LT, PassportApplyOrder.STAUTS_SEND_WAITE));
        else
            filters.put("status", new SearchFilter("status", SearchFilter.Operator.EQ, status));
        filters.put("cardNO", new SearchFilter("cardNO", SearchFilter.Operator.LIKE, cardNO));
        Specification<PassportApplyOrder> spec = DynamicSpecifications.bySearchFilter(filters.values(), PassportApplyOrder.class);
        return this.passportApplyOrderDao.findAll(spec,pageRequest);
    }

    @Override
    public Page<PassportApplyOrder> findByPassportNO(Long baseAddressId, String passportNO, int status, int pageNumber) throws ServiceRuntimeException
    {
        Map<String, SearchFilter> filters = Maps.newHashMap();
        Sort sort = new Sort(Sort.Direction.DESC, "appointmentTime");
        PageRequest pageRequest = new PageRequest(pageNumber - 1, 20, sort);
        filters.put("bassAddressId", new SearchFilter("bassAddressId", SearchFilter.Operator.EQ, baseAddressId));
        filters.put("orderStatus", new SearchFilter("orderStatus", SearchFilter.Operator.EQ, PassportApplyOrder.ORDER_STAUTS_NORMAL));
        if(status<PassportApplyOrder.STAUTS_SEND_WAITE)
            filters.put("status", new SearchFilter("status", SearchFilter.Operator.LT, PassportApplyOrder.STAUTS_SEND_WAITE));
        else
            filters.put("status", new SearchFilter("status", SearchFilter.Operator.EQ, status));
        filters.put("passportNO", new SearchFilter("passportNO", SearchFilter.Operator.LIKE, passportNO));
        Specification<PassportApplyOrder> spec = DynamicSpecifications.bySearchFilter(filters.values(), PassportApplyOrder.class);
        return this.passportApplyOrderDao.findAll(spec,pageRequest);
    }

    @Override
    public PassportApplyOrder findByPassportNO(String passportNO) throws ServiceRuntimeException
    {
        Map<String, SearchFilter> filters = Maps.newHashMap();
        Sort sort = new Sort(Sort.Direction.DESC, "appointmentTime");
        PageRequest pageRequest = new PageRequest(0, 20, sort);
        filters.put("passportNO", new SearchFilter("passportNO", SearchFilter.Operator.LIKE, passportNO));
        Specification<PassportApplyOrder> spec = DynamicSpecifications.bySearchFilter(filters.values(), PassportApplyOrder.class);
        Page<PassportApplyOrder> data =  this.passportApplyOrderDao.findAll(spec,pageRequest);
        if(null == data || data.getContent() == null || data.getContent().size() == 0)
            return null;
        else
            return data.getContent().get(0);
    }

    @Override
    public void lock(Long id,PassportApplyOrderPatch patch) throws ServiceRuntimeException
    {
        PassportApplyOrder passportApplyOrder = this.findOne(id);
        passportApplyOrder.setStatus(PassportApplyOrder.STAUTS_WAITE_LOGOUT);
        passportApplyOrder.setBackStatus(PassportApplyOrder.BACK_STATUS_SEND);
        this.save(passportApplyOrder);
        passportApplyOrderPatchService.save(patch);
    }

    @Override
    public String createPassportNO() throws ServiceRuntimeException
    {
        synchronized(this)
        {
            String passPortNO = "310000001000010001";
            Map<String, SearchFilter> filters = Maps.newHashMap();
            Sort sort = new Sort(Sort.Direction.DESC, "passportNO");
            PageRequest pageRequest = new PageRequest(0,1, sort);
            Specification<PassportApplyOrder> spec = DynamicSpecifications.bySearchFilter(filters.values(), PassportApplyOrder.class);
            Page<PassportApplyOrder> data = this.passportApplyOrderDao.findAll(spec,pageRequest);
            if(null != data && null != data.getContent() && data.getContent().size()>0)
            {
                PassportApplyOrder lastOrder = data.getContent().get(0);
                String lastNO = lastOrder.getPassportNO().replace("310000001","");
                //000000002
                //如果前5位都是0则给出
                if(lastNO.contains("00000"))
                    return passPortNO;
                //000010001

            }
            return passPortNO;
        }

    }
}
